import { cloneDeep } from "lodash-es"

export interface TreeNodeProps {
  idKey?: string
  parentIdKey?: string
  nameKey?: string
  childrenKey?: string
  sortKey?: string,
  rowHandle?: Function // 行处理
}
export class TreeNode<T> {
  idKey: string
  parentIdKey: string
  nameKey: string
  childrenKey: string
  sortKey: string
  rowHandle?: Function
  constructor(props: TreeNodeProps) {
    this.idKey = props.idKey || 'id';
    this.nameKey = props.nameKey || 'name';
    this.parentIdKey = props.parentIdKey || 'parentId';
    this.childrenKey = props.childrenKey || 'children';
    this.sortKey = props.sortKey || 'sort';
    this.rowHandle = props.rowHandle
  }
  /**
   * 构建树
   * @param data 
   * @param parentId 
   * @returns 
   */
  public build(data: Array<T>, parentId: string | number): Array<T> {
    const copyData = cloneDeep(data)
    return this._build(copyData, parentId)
  }
  /**
   * 构建树
   * @param data 
   * @param parentId 
   * @returns 
   */
   private _build(data: Array<T>, parentId: string | number): Array<T> {
    const res : Array<any> = []
    if(!data.length) return res;
    const list = this.findByParentId(data, parentId)
    res.push(...list)
    list.forEach((item: any)=>{
      const children = this.findByParentId(data, item.id)
      if(children.length) {
        item[this.childrenKey] = children
        children.forEach((itemm: any)=>{
          itemm[this.childrenKey] = this._build(data, itemm.id)
          if(!itemm[this.childrenKey].length) {
            itemm[this.childrenKey] = undefined
          }
          if(this.rowHandle && typeof this.rowHandle == 'function') {
            this.rowHandle(itemm)
          }
        })
      } else {
        item[this.childrenKey] = undefined
      }
      if(this.rowHandle && typeof this.rowHandle == 'function') {
        this.rowHandle(item)
      }
    })
    return res;
  }
  /**
   * 通过父id获取所有子元素
   * @param data 
   * @param parentId 
   * @returns 
   */
  public findByParentId(data: Array<T>, parentId: string | number): Array<T> {
    return data.filter((item: any)=>{
      return item[this.parentIdKey] == parentId && item[this.idKey] && item[this.nameKey]
    }).sort((a, b) =>{
      return (a[this.sortKey] || 999) - (b[this.sortKey] || 999)
    })
  }
  /**
   * 获取节点中的所有子ids
   * @param nodeData 节点
   * @param hasSelf 是否包含自身
   * @returns 
   */
  public getChildIds(nodeData: any,hasSelf: boolean): [] {
    const res : any = []
    if(!nodeData) {
      return res;
    }
    if(hasSelf) {
      res.push(nodeData?.[this.idKey])
    }
    if(nodeData?.[this.childrenKey]) {
      nodeData?.[this.childrenKey].forEach((child: any) =>{
        res.push(...this.getChildIds(child, true))
      })
    }
    return res;
  }
}